package com.iwayin.core.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;

import org.apache.commons.beanutils.BeanUtils;

/************************************************
 * Copyright (c) by liujian
 * All right reserved.
 * Create Date: Apr 11, 2010
 * Create Author: liujian
 * File Name: BeanUtil.java
 * Last version: 1.0
 * Function: 操作JavaBean的工具类
 * Last Update Date:
 * Change Log:
**************************************************/
@SuppressWarnings("unchecked")
public class BeanUtil extends BeanUtils {

	private BeanUtil() {}
	/**
	 * 通过属性名获取属性对象
	 * @param object 对象
	 * @param name 属性名
	 * @return 属性对象
	 */
	public static final Field getDeclaredProperty(Object object, String name) {
		return null != object ? getDeclaredProperty(object.getClass().getName(), name) : null;
	}
	
	/**
	 * 通过属性名获取属性对象
	 * @param className 类名
	 * @param name 属性名
	 * @return 属性对象
	 */
	public static final Field getDeclaredProperty(String className, String name) {
		Field f = null;
		try {
			if (StringUtil.isNotEmptyAll(className, name)) {
				Class clazz = Class.forName(className);
				f = clazz.getDeclaredField(name);
			}
		} catch (SecurityException e) {
		} catch (NoSuchFieldException e) {
		} catch (ClassNotFoundException e) {
		}
		return f;
	}
	
	/**
	 * 通过属性获取相应的值
	 * @param object 对象
	 * @param name 属性名
	 * @return 相应的值
	 */
	public static final Object getValueByProperty(Object object, String name) {
		Object result = null;
		if (null != object && StringUtil.isNotBlank(name)) {
			Field field = getDeclaredProperty(object, name);
			if (null != field) {
				boolean accessible = field.isAccessible();
				field.setAccessible(true);
				try {
					result = field.get(object);
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				}
				field.setAccessible(accessible);
			}
		}
		return result;
	}
	
	/**
	 * 通过属性名赋值给该属性
	 * @param object 对象
	 * @param name 属性名
	 * @param value 值
	 */
	public static final void setValueByProperty(Object object, String name, Object value) {
		if (null != object) {
			Field field = getDeclaredProperty(object, name);
			if (null != field) {
				boolean accessible = field.isAccessible();
				field.setAccessible(true);
				try {
					field.set(object, value);
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				}
				field.setAccessible(accessible);
			}
		}
	}
	
	/**
	 * 通过方法名获取方法对象
	 * @param object 对象
	 * @param name 方法名
	 * @param args 参数类型
	 * @return 方法对象
	 */
	public static final Method getDeclaredMethod(Object object, String name, Object... args) {
		return null != object ? getDeclaredMethod(object.getClass().getName(), name, args) : null;
	}
	
	/**
	 * 通过方法名获取方法对象
	 * @param className 类名
	 * @param name 方法名
	 * @param args 参数类型
	 * @return 方法对象
	 */
	public static final Method getDeclaredMethod(String className, String name, Object... args) {
		Method m = null;
		if (StringUtil.isNotEmptyAll(className, name) && null != args) {
			Class[] types = new Class[args.length];
			for (int i = 0; i < args.length; i++) {
				types[i] = args[i].getClass();
			}
			try {
				Class clazz = Class.forName(className);
				m = clazz.getDeclaredMethod(name, types);
			} catch (SecurityException e) {
			} catch (NoSuchMethodException e) {
			} catch (ClassNotFoundException e) {
			}
		}
		return m;
	}
	
	/**
	 * 动态调用方法
	 * @param object 对象
	 * @param name 方法名
	 * @param args 参数类型
	 * @return 方法对象
	 */
	public static final Method invokeMethod(Object object, String name, Object... args) {
		Method m = null;
		if (null != object && StringUtil.isNotBlank(name) && null != args) {
			Method method = getDeclaredMethod(object, name, args);
			if (null != method) {
				boolean accessible = method.isAccessible();
				method.setAccessible(true);
				try {
					m = (Method) method.invoke(object, args);
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				} catch (InvocationTargetException e) {
				}
				method.setAccessible(accessible);
			}
		}
		return m;
	}
	
	/**
	 * 拷贝超类的属性
	 * @param dest 目标对象
	 * @param source 源对象
	 */
	public static final void copySuperProperties(Object dest, Object source) {
		if (null != dest && null != source) {
			Field[] fields = getSuperProperties(source);
			if (null != fields) {
				for (Field f : fields) {
					Object value = getValueByProperty(source, f.getName());
					setValueByProperty(dest, f.getName(), value);
				}
			}
		}
	}
	
	/**
	 * 获取对象超类的属性
	 * @param object 对象
	 * @return Field[]
	 */
	public static final Field[] getSuperProperties(Object object){
		Field[] f = null;
		if (null != object) {
			Class superClass = object.getClass().getSuperclass();
			if (null != superClass) {
				f = superClass.getDeclaredFields();
			}
		}
		return f;
	}
	
	/**
	 * 拷贝类的属性(不包括继承的)
	 * @param dest 目标对象
	 * @param source 源对象
	 */
	public static final void copySelfProperties(Object dest, Object source) {
		if (null != dest && null != source) {
			Field[] fields = getProperties(source);
			if (null != fields) {
				for (Field f : fields) {
					Object value = getValueByProperty(source, f.getName());
					setValueByProperty(dest, f.getName(), value);
				}
			}
		}
	}
	
	/**
	 * 获取对象的属性(不包括继承类)
	 * @param object 对象
	 * @return Field[]
	 */
	public static final Field[] getProperties(Object object) {
		Field[] field = null;
		if (null != object) {
			Class c = object.getClass();
			field = c.getDeclaredFields();
		}
		return field;
	}
	
	/**
	 * 把字符串转化成对应的类型的值
	 * @param clazz 类型的类(String.class, Double.class, Integer.class, Date.class, Long.class)
	 * @param value 字符串值
	 * @return 转化后的值
	 */
	public static final Object getStringToType(Class clazz, String value) {
		Object obj = null;
		if (clazz.equals(String.class)) {
			if (null == value) {
				obj = "";
			} else {
				obj = String.valueOf(value);
			}
		} else if (clazz.equals(Double.class)) {
			if (null == value) {
				obj = 0D;
			} else {
				obj = Double.valueOf(value);
			}
		} else if (clazz.equals(Integer.class)) {
			if (null == value) {
				obj = 0;
			} else {
				obj = Integer.valueOf(value).intValue();
			}
		} else if (clazz.equals(Date.class)) {
			if (null == value) {
				obj = null;
			} else {
				obj = DateTimeUtil.getFormatDate(value, DateTimeUtil.DATE_FORMAT);
			}
		} else if (clazz.equals(Long.class)) {
			if (null == value) {
				obj = 0L;
			} else {
				obj = Double.valueOf(value).longValue();
			}
		}
		return obj;
	}
}